`include "defines.v"
module DcacheHasMmio(
  input clk,
  input rst_n,
  input invalidate,
  // LSU 访问的接口
  input lsu_dcache_addr_valid_i,
  input [`ADDR_W-1:0]lsu_dcache_addr_i,
  input [7:0] lsu_dcache_strb_i,
  input lsu_dcache_wen_i,
  input lsu_dcache_invalidate_i,
  input [63:0] lsu_dcache_wdata_i,
  output [63:0] dcache_lsu_rdata_o,
  output dcache_lsu_data_valid_o,
  // 下游访问接口 L2Cache 或内存
  output dcache_mem_addr_valid_o,
  output dcache_mem_wen_o,
  output [`ADDR_W-1:0] dcache_mem_addr_o,
  output [127:0] dcache_mem_wdata_o,
  output [7:0] dcache_mem_strb_o,
  input  mem_dcache_data_valid_i,
  input  [127:0] mem_dcache_rdata_i
);
wire isMMIO = lsu_dcache_addr_valid_i && ~lsu_dcache_addr_i[`PADDR_W-1] && ~lsu_dcache_invalidate_i;

wire dcache_addr_valid_i         ;
wire [`ADDR_W-1:0] dcache_addr_i ;
wire [7:0]  dcache_strb_i        ;
wire dcache_wen_i                ;
wire [63:0]  dcache_wdata_i      ;
wire [63:0] dcache_rdata_o       ;
wire dcache_data_valid_o         ;

wire  mem_addr_valid_o         ;
wire  mem_wen_o                ;
wire  [`ADDR_W-1:0] mem_addr_o ;
wire  [127:0] mem_wdata_o      ;
wire  mem_data_valid_i         ;
wire [127:0] mem_rdata_i       ;

Dcache dcache(
  .clk(clk),
  .rst_n(rst_n),
  .invalidate(invalidate), // 刷新meta中的有效位
  // LSU 访问的接口
  .lsu_dcache_addr_valid_i (dcache_addr_valid_i ),
  .lsu_dcache_addr_i       (dcache_addr_i       ),
  .lsu_dcache_strb_i       (dcache_strb_i       ),
  .lsu_dcache_wen_i        (dcache_wen_i        ),
  .lsu_dcache_invalidate_i (lsu_dcache_invalidate_i),
  .lsu_dcache_wdata_i      (dcache_wdata_i      ),
  .dcache_lsu_rdata_o      (dcache_rdata_o      ),
  .dcache_lsu_data_valid_o (dcache_data_valid_o ),
  // 下游访问接口 L2Cache或内存
  .dcache_mem_addr_valid_o (mem_addr_valid_o ),
  .dcache_mem_wen_o        (mem_wen_o        ),
  .dcache_mem_addr_o       (mem_addr_o       ),
  .dcache_mem_wdata_o      (mem_wdata_o      ),
  .mem_dcache_data_valid_i (mem_data_valid_i ),
  .mem_dcache_rdata_i      (mem_rdata_i      )
);
// Dcache 请求
assign dcache_addr_valid_i = ~isMMIO && lsu_dcache_addr_valid_i ;
assign dcache_addr_i       = lsu_dcache_addr_i;
assign dcache_strb_i       = lsu_dcache_strb_i;
assign dcache_wen_i        = ~isMMIO && lsu_dcache_wen_i;
assign dcache_wdata_i      = lsu_dcache_wdata_i;
// Dcache 回复
assign mem_data_valid_i    =  ~isMMIO && mem_dcache_data_valid_i;
assign mem_rdata_i         =  mem_dcache_rdata_i;
// 访存请求
assign dcache_mem_addr_valid_o =  isMMIO ? lsu_dcache_addr_valid_i  : mem_addr_valid_o;  
assign dcache_mem_wen_o        =  isMMIO ? lsu_dcache_wen_i         : mem_wen_o       ;
assign dcache_mem_addr_o       =  isMMIO ? lsu_dcache_addr_i        : mem_addr_o      ;  
assign dcache_mem_wdata_o      =  isMMIO ? lsu_dcache_wdata_i[63:0] : mem_wdata_o     ; 
assign dcache_mem_strb_o       =  lsu_dcache_strb_i;
// 访存回复
assign  dcache_lsu_data_valid_o = isMMIO ? mem_dcache_data_valid_i  : dcache_data_valid_o;
assign  dcache_lsu_rdata_o      = isMMIO ? mem_dcache_rdata_i[63:0] : dcache_rdata_o     ;
endmodule